package com.neusoft.bizcore.notice.notification.factory.impl;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.transaction.Transactional;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.neusoft.bizcore.notice.constant.NoticeConsts;
import com.neusoft.bizcore.notice.notification.dto.NoticeRecordDTO;
import com.neusoft.bizcore.notice.notification.dto.NoticeRecordMailDTO;
import com.neusoft.bizcore.notice.notification.dto.NoticeTemplateAttachmentDTO;
import com.neusoft.bizcore.notice.notification.dto.NoticeTemplateDTO;
import com.neusoft.bizcore.notice.notification.factory.MessageFactory;
import com.neusoft.bizcore.notice.notification.model.enums.SendStatus;
import com.neusoft.bizcore.notice.notification.service.NoticeTemplateService;
import com.neusoft.bizcore.notice.notification.util.DatabaseTemplateLoader;

import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;

/**
 * 发送消息map中必须有的字段 string emailAddress 收件人列表，如果是多个，以逗号分隔 string title 邮件主题
 *
 * @author wangsi
 */

@Slf4j
@Service
public class MailMessageFactory implements MessageFactory {
    @Autowired
    private FreeMarkerConfigurer configurer;
    @Autowired
    private ApplicationContext context;
    @Autowired
    private Environment environment;
    @Autowired
    private NoticeTemplateService noticeTemplateService;

    @Override
    @Transactional
    public void sendMessage(final NoticeRecordDTO msg) {
        MailMessageFactory.log.info("邮件消息 发送开始----------");

        NoticeRecordMailDTO mailDTO = msg.getMail();
        //发送者
        final String username = this.environment.getProperty("spring.mail.username");
        String errorMsg = NoticeConsts.INFORM_TYPE_MAIL + NoticeConsts.NOTICE_SEND_SUCCESS;
        String status = SendStatus.success.toString();
        try {
            if ((mailDTO != null) && !StringUtils.isEmpty(username)) {
                final JavaMailSenderImpl mailSender = this.context.getBean(JavaMailSenderImpl.class);
                final MimeMessage mimeMessage = mailSender.createMimeMessage();
                final MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
                helper.setFrom(username);//发送者
                helper.setTo(InternetAddress.parse(mailDTO.getEmailAddress()));//发送给谁
                helper.setSubject(
                        "【" + msg.getTitle() + "-" + LocalDate.now() + " " + LocalTime.now().withNano(0) + "】");//邮件标题
                final Map<String, Object> templateData = new HashMap<>();
                final JSONObject templateMsg = JSON.parseObject(mailDTO.getTemplateMsg());
                final Iterator<Map.Entry<String, Object>> iterator = templateMsg.entrySet().iterator();
                while (iterator.hasNext()) {
                    final Map.Entry<String, Object> entry = iterator.next();
                    templateData.put(entry.getKey(), entry.getValue());
                }

                Template template;
                // 用户自定义模板存在，则使用用户自定义模板。否则使用系统内置模板。
                if (this.checkUserDefinedTemplate(mailDTO.getTemplateName())) {
                    final Configuration cfg = this.configurer.getConfiguration();
                    final TemplateLoader templateLoader = new DatabaseTemplateLoader();
                    cfg.setTemplateLoader(templateLoader);

                    template = cfg.getTemplate(mailDTO.getTemplateName());
                } else {
                    final Configuration cfg = this.configurer.getConfiguration();
                    final TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass(), "/templates");
                    cfg.setTemplateLoader(templateLoader);

                    template = cfg.getTemplate("noticeMail.ftl");
                }

                final String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, templateData);
                helper.setText(text, true);
                mailSender.send(mimeMessage);
                MailMessageFactory.log.info(errorMsg);
            } else {
                status = SendStatus.failure.toString();
            }
        } catch (final Exception e1) {
            status = NoticeConsts.NOTICE_SEND_FAILURE;
            errorMsg = NoticeConsts.INFORM_TYPE_MAIL + NoticeConsts.NOTICE_SEND_FAILURE + " : " + e1.getMessage();
            MailMessageFactory.log.error(errorMsg, e1);
        } finally {
            if (mailDTO == null) {
                mailDTO = new NoticeRecordMailDTO();
                msg.setMail(mailDTO);
                errorMsg = NoticeConsts.INFORM_TYPE_MAIL + NoticeConsts.NOTICE_SEND_FAILURE + ","
                        + NoticeConsts.NOTICE_NO_MSG;
            }
            if (StringUtils.isEmpty(username)) {
                errorMsg = NoticeConsts.INFORM_TYPE_MAIL + NoticeConsts.NOTICE_SEND_FAILURE + ","
                        + NoticeConsts.NOTICE_NO_MAIL_SERVER;
            }
            mailDTO.setErrorMsg(errorMsg);
            mailDTO.setStatus(status);
            MailMessageFactory.log.info("邮件消息 发送结束----------: " + errorMsg);
        }

    }

    /**
     * 检查是否存在用户自定义模板
     *
     * @param noticeTempLateList
     * @return
     */
    private boolean checkUserDefinedTemplate(final String templateCode) {
        final NoticeTemplateDTO noticeTempLate = this.noticeTemplateService.findByType(templateCode);
        if (noticeTempLate != null) {
            final NoticeTemplateAttachmentDTO attachment = noticeTempLate.getTemplate();
            if (attachment != null) {
                return true;
            }
        }
        return false;
    }
}
